﻿using System;
using System.Linq;
using DependencyAnalysis;
using DependencyAnalysis.DataModel;
using NUnit.Framework;

namespace NUnitExample
{
    [TestFixture]
    public class MethodQualityTest : DependencyTest
    {
        [Test]
        public void NumberOfParametersIsAtMost3()
        {
            Func<MemberDescriptor, State, bool> assumption = (x, y) =>
                {
                    var value = Setup.Metrics.NumberOfParameters(x);
                    y.Message = "" + value;
                    return x.IsOverride || x.IsDefinedByInterface || value <= 3;
                };

            Verifier.VerifyThat(assumption, x => Filters.MyMembers(x) && x.Name != ".ctor");
        }

        [Test]
        public void NumberOfInstructionsIsAtMost200()
        {
            Func<MemberDescriptor, State, bool> assumption = (x, y) =>
            {
                if (x.Name == ".cctor") return true;
                var value = Setup.Metrics.NumberOfInstructions(x);
                y.Message = "" + value;
                return value <= 200;
            };

            Verifier.VerifyThat(assumption, x => Filters.MyMembers(x) && !IsDynamicMethod(x));
        }

        [Test]
        public void CyclomaticComplexityIsAtMost20()
        {
            Func<MemberDescriptor, State, bool> assumption = (x, y) =>
            {
                var value = Setup.Metrics.CyclomaticComplexity(x);
                y.Message = "" + value;
                return value <= 20;
            };

            Verifier.VerifyThat(assumption, x => Filters.MyMembers(x) && !IsDynamicMethod(x));
        }

        private static bool IsDynamicMethod(MemberDescriptor member)
        {
            return member.MemberType == MemberType.Method &&
                   Setup.Model.DependenciesPerMemberOut[member].Any(
                       x => x.Target.ImplementingType.FullName == "Microsoft.CSharp.RuntimeBinder.Binder");
        }

        [Test]
        public void NestingDepthIsAtMost6()
        {
            Func<MemberDescriptor, State, bool> assumption = (x, y) =>
            {
                var value = Setup.Metrics.NestingDepth(x);
                y.Message = "" + value;
                return value <= 6;
            };

            Verifier.VerifyThat(assumption, Filters.MyMembers);
        }


        [Test]
        public void NumberOfParametersIsAtMost4()
        {
            Verifier.VerifyThat((x, state) =>
            {
                if (x.Name == ".ctor") return true;
                var c = Setup.Metrics.NumberOfParameters(x);
                if (c > 4 && !x.IsOverride && !x.IsDefinedByInterface)
                {
                    state.Message = string.Format("'number of parameters={0} > 4'", c);
                    return false;
                }
                return true;
            }, Filters.MyMembers);
        }
    }
}
